package com.yangaobo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yangaobo.dto.MenuInsertDTO;
import com.yangaobo.dto.MenuPageDTO;
import com.yangaobo.dto.MenuUpdateDTO;
import com.yangaobo.entity.Menu;
import com.yangaobo.excel.MenuExcel;
import com.yangaobo.exception.ServerErrorException;
import com.yangaobo.mapper.MenuMapper;
import com.yangaobo.service.MenuService;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 杨奥博
 */
@Service
@CacheConfig(cacheNames = "menu")
public class MenuServiceImpl implements MenuService {
    @Resource
    private MenuMapper menuMapper;

    @CacheEvict(allEntries = true)
    @Override
    public int insert(MenuInsertDTO dto) {
        // 将DTO转换为Entity（使用Hutool工具类BeanUtil复制属性）
        Menu menu = BeanUtil.copyProperties(dto, Menu.class);
        if (dto.getPid() != null && dto.getPid().equals(0L)) {
            menu.setUrl("/");
        }
        if (StrUtil.isBlank(dto.getInfo())) {
            menu.setInfo("暂无描述");
        }
        menu.setVersion(0L);
        menu.setDeleted(0);
        menu.setCreated(LocalDateTime.now());
        menu.setUpdated(LocalDateTime.now());
        int result = menuMapper.insert(menu);
        if (result <= 0) {
            throw new ServerErrorException("DB添加失败");
        }
        return result;
    }

    @Cacheable(key = "#p0", condition = "#p0 != null", unless = "#result == null")
    @Override
    public Menu select(Long id) {
        Menu result = menuMapper.select(id);
        if (ObjectUtil.isNull(result)) {
            throw new ServerErrorException("DB查询失败");
        }
        return result;
    }

    @Cacheable(key = "#root.methodName", unless = "#result == null")
    @Override
    public List<Menu> list() {
        return menuMapper.list(new MenuPageDTO())
                .stream()
                .map(menu -> BeanUtil.copyProperties(menu, Menu.class))
                .collect(Collectors.toList());
    }

    @Cacheable(key = "#root.methodName + ':' + #p0.toString()",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public PageInfo<Menu> page(MenuPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return new PageInfo<>(menuMapper.list(dto));
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(MenuUpdateDTO dto) {
        Menu menu = menuMapper.select(dto.getId());
        if (ObjectUtil.isNull(menu)) {
            throw new ServerErrorException("DB查询失败");
        }
        // 将DTO中的值复制到Entity中
        BeanUtil.copyProperties(dto, menu);
        // 设置默认值
        menu.setUpdated(LocalDateTime.now());
        // DB修改
        int result = menuMapper.update(menu);
        if (result <= 0) {
            throw new ServerErrorException("DB修改失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int delete(Long id) {
        int result = menuMapper.delete(id);
        if (result <= 0) {
            throw new ServerErrorException("DB删除失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int deleteBatch(List<Long> ids) {
        int result = menuMapper.deleteBatch(ids);
        if (result <= 0) {
            throw new ServerErrorException("DB删除失败");
        }
        return result;
    }


    public List<MenuExcel> getExcelData() {
        return menuMapper.list(new MenuPageDTO())
                .stream()
                .map(menu -> BeanUtil.copyProperties(menu, MenuExcel.class))
                .collect(Collectors.toList());
    }

    @Cacheable(key = "#root.methodName + ':' + #p0",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public List<Menu> listByRoleId(Long roleId) {
        return menuMapper.listByRoleId(roleId);
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateByRoleId(Long roleId, List<Long> ids) {
        List<Menu> menus = menuMapper.listByRoleId(roleId);
        if (!menus.isEmpty()) {
            int result = menuMapper.deleteByRoleId(roleId);
            if (result <= 0) {
                throw new ServerErrorException("DB删除失败");
            }
        }

        if(CollectionUtil.isEmpty(ids)) {
            return 1;
        }
        int result = menuMapper.updateByRoleId(roleId, ids);
        if (result <= 0) {
            throw new ServerErrorException("DB修改失败");
        }
        return result;
    }

    @Cacheable(key = "#root.methodName + ':' + #p0",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public List<Menu> listByEmpId(Long empId) {
        return menuMapper.listByEmpId(empId);
    }

}
